﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace Passwords.Biz
{
    public class Password : Entity
    {
        private bool isFavoriteUndo;
        private string nameUndo;

        private bool isFavorite;
        private EntityCollection<Category> categories;
        private EntityCollection<PasswordItem> items;
        private EntityCollection<PasswordItem> editItems;


        public Password(int id, string name, bool isFavorite)
            : base(id, name)
        {
            this.isFavorite = isFavorite;
            isFavoriteUndo = isFavorite;
            nameUndo = name;
        }

        public Password()
            : base()
        {
            EntityState = EntityState.New;
        }

        public bool IsFavoriteModified
        {
            get { return isFavoriteUndo != isFavorite; }
        }

        public bool IsFavorite
        {
            get { return isFavorite; }
            set
            {
                isFavorite = value;
                OnPropertyChanged("IsFavorite");
            }
        }

        public IList<PasswordItem> Items
        {
            get
            {
                if (items == null)
                {
                    PasswordItem[] a = new PasswordItem[] { new CategoryPasswordItem(this) };
                    items = new EntityCollection<PasswordItem>(this, "Items", a);
                }
                return items.OrderBy(i => i.DisplayIndex).ToList();
            }

            set
            {
                items = new EntityCollection<PasswordItem>(this, "Items", value);
            }
        }

        public IList<PasswordItem> EditItems
        {
            get
            {
                if (editItems == null) editItems = new EntityCollection<PasswordItem>(this, "EditItems", Context.GetEditItems(this));
                return editItems;
            }
        }

        public IList<Category> Categories
        {
            get
            {
                if (categories == null) categories = new EntityCollection<Category>(this, "Categories", Context.GetCategories(this));
                return categories;
            }

            set
            {
                categories = new EntityCollection<Category>(this, "Categories", value);
                if (editItems != null) UpdateEditItemsFromCategories();
            }
        }

        private void UpdateEditItemsFromCategories()
        {
            Items = (from i in editItems where i.ValueType == ItemType.Categories || (!i.IsReadonly && !i.IsEmpty) orderby i.DisplayIndex select i).ToArray();
            editItems = null;
        }

        public void Undo()
        {
            if (editItems != null)
            {
                foreach (var item in editItems) item.Undo();
            }
            categories = null;
            isFavorite = isFavoriteUndo;
            Name = nameUndo;
            EntityState = EntityState.Unchanged;
        }

        public void Save()
        {
            UpdateItems();
            Context.Save(this);
            nameUndo = Name;
            isFavoriteUndo = isFavorite;
            EntityState = EntityState.Unchanged;
        }

        public void UpdateItems()
        {
            if (editItems != null)
            {
                foreach (var item in editItems) item.Save();
                Items = (from item in editItems where !item.IsReadonly && !item.IsEmpty orderby item.DisplayIndex select item).ToArray();
                editItems = null;
            }
        }

        public void Delete()
        {
            Context.Delete(this);
            categories = null;
            items = null;
            editItems = null;
            EntityState = EntityState.Deleted;
        }


        internal IEnumerable<PasswordItem> GetItemsToView()
        {
            return Items;
        }

        public string CategoriesToString()
        {
            StringBuilder sb = new StringBuilder();

            foreach (var c in Categories)
            {
                if (sb.Length > 0) sb.AppendLine();
                sb.AppendFormat("• {0}", c.Name);
            }
            return sb.ToString();
        }


        public void AddItem(PasswordItem item)
        {
            int index = GetInsertIndex(item.DisplayIndex);
            EditItems.Insert(index, item);
        }

        private int GetInsertIndex(int index)
        {
            int n = EditItems.Count - 1;
            for (int i = 0; i < n; i++)
            {
                if (EditItems[i].DisplayIndex > index) return i;
            }
            return n;
        }
    }
}
